package com.zy.service;

import java.util.concurrent.TimeUnit;

import javax.annotation.PostConstruct;

import com.google.common.cache.Cache;
import com.zy.domain.Account;
import com.zy.repository.AccountDao;
import com.zy.service.exception.ErrorCode;
import com.zy.service.exception.ServiceException;
import com.zy.utils.Digests;
import com.zy.utils.Encodes;
import com.zy.utils.Ids;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.boot.actuate.metrics.CounterService;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;




import com.google.common.cache.CacheBuilder;

// Spring Bean的标识.
@Service
public class AccountService {

    private static Logger logger = LoggerFactory.getLogger(AccountService.class);

    @Autowired
    private AccountDao accountDao;

    // 注入配置值
    @Value("${app.loginTimeoutSecs:600}")
    private int loginTimeoutSecs;

    // codehale metrics
    @Autowired
    private CounterService counterService;

    // guava cache
    private Cache<String, Account> loginUsers;

    @PostConstruct
    public void init() {
        loginUsers = CacheBuilder.newBuilder().maximumSize(1000).expireAfterAccess(loginTimeoutSecs, TimeUnit.SECONDS)
                .build();
    }

    @Transactional(readOnly = true)
    public String login(String email, String password) {
        Account account = accountDao.findByEmail(email);

        if (account == null) {
            throw new ServiceException("User not exist", ErrorCode.UNAUTHORIZED);
        }

        if (!account.hashPassword.equals(hashPassword(password))) {
            throw new ServiceException("Password wrong", ErrorCode.UNAUTHORIZED);
        }

        String token = Ids.uuid2();
        loginUsers.put(token, account);
        counterService.increment("loginUser");
        return token;
    }

    public void logout(String token) {
        Account account = loginUsers.getIfPresent(token);
        if (account == null) {
            logger.warn("logout an alreay logout token:" + token);
        } else {
            loginUsers.invalidate(token);
            counterService.decrement("loginUser");
        }
    }

    public Account getLoginUser(String token) {

        Account account = loginUsers.getIfPresent(token);

        if (account == null) {
            throw new ServiceException("User doesn't login", ErrorCode.UNAUTHORIZED);
        }

        return account;
    }

    @Transactional
    public void register(String email, String name, String password) {

        if (StringUtils.isBlank(email) || StringUtils.isBlank(password)) {
            throw new ServiceException("Invalid parameter", ErrorCode.BAD_REQUEST);
        }

        Account account = new Account();
        account.email = email;
        account.name = name;
        account.hashPassword = hashPassword(password);
        accountDao.save(account);
    }

    protected static String hashPassword(String password) {
        return Encodes.encodeBase64(Digests.sha1(password));
    }
}
